package cn.zxf.note.note.parse;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 解析日记
 * <p>
 * Created by zengxf on 2019-06-19
 */
@Slf4j
public class ParseDayNote {

    private String file;
    private String content;

    public static ParseDayNote of(String file) {
        ParseDayNote parser = new ParseDayNote();
        parser.file = file;
        return parser;
    }

    public DayNoteVo parse() throws IOException {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(this.file), StandardCharsets.UTF_8))) {
            return this.parse(br);
        }
    }

    public static ParseDayNote ofContent(String content) {
        ParseDayNote parser = new ParseDayNote();
        parser.content = content;
        return parser;
    }

    public DayNoteVo parseContent() throws IOException {
        Reader inputString = new StringReader(this.content);
        try (BufferedReader br = new BufferedReader(inputString)) {
            return this.parse(br);
        }
    }

    public DayNoteVo parse(BufferedReader br) throws IOException {
        String line;
        boolean day = false;
        List<String> list = new ArrayList<>();
        while ((line = br.readLine()) != null) {
            if (line.startsWith("## ")) {
                day = true;
                list.add(line);
            } else if (!day && line.startsWith("### ")) {
                day = true;
                list.add("## " + LocalDate.now().getDayOfMonth()); // 默认当天
                list.add(line);
            } else if (day) {
                list.add(line);
            }
        }
        return parseDayNote(list);
    }

    static DayNoteVo parseDayNote(List<String> list) {
        String first = list.get(0);
        String day = parseDay(first);
        log.debug("day-note: {}", day);
        int i = 1;
        while (!list.get(i).startsWith("### "))
            i++;
        List<NoteVo> notes = new ArrayList<>();
        String second = list.get(i++);
        String typeV = parseValue(second, "### (.+)", "类型格式不对：");
        log.debug("day-note-typeV: {}", typeV);
        List<String> items = new ArrayList<>();
        for (; i < list.size(); i++) {
            String line = list.get(i);
            if (line.startsWith("### ")) {
                notes.addAll(parseTypeNote(typeV, items));
                items.clear();
                typeV = parseValue(line, "### (.+)", "类型格式不对：");
                log.debug("day-note-typeV: {}", typeV);
            } else
                items.add(line);
        }
        notes.addAll(parseTypeNote(typeV, items));
        return new DayNoteVo(day, notes);
    }

    static List<NoteVo> parseTypeNote(String type, List<String> list) {
        String first = list.get(0);
        String title = parseValue(first, "#### (.+)", "标题格式不对：");
        log.debug("title: {}", title);
        List<String> items = new ArrayList<>();
        List<NoteVo> notes = new ArrayList<>();
        for (int i = 1; i < list.size(); i++) {
            String line = list.get(i);
            if (line.startsWith("#### ")) {
                notes.add(new NoteVo(type, title, items));
                items = new ArrayList<>();
                title = parseValue(line, "#### (.+)", "标题格式不对：");
                log.debug("title: {}", title);
            } else
                items.add(line);
        }
        notes.add(new NoteVo(type, title, items));
        return notes;
    }

    static String parseDay(String str) {
        return parseValue(str, ".*?(\\d{2})", "日期格式不对：");
    }

    static String parseValue(String str, String regex, String errMsg) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        if (matcher.find()) {
            return matcher.group(1);
        } else {
            throw ParseNoteException.of(errMsg + str);
        }
    }

}
